Skip to main content

ติดตั้ง GraphQL บน Firebase Cloud Functions

·3 mins

โลกหมุนเร็วขึ้นทุกวัน จากที่ RESTful API เคยยืนหนึ่งไร้เทียมทานทุกวันนี้ก็มีคนเสนอแนวคิดใหม่ๆในการสร้างระบบ API หนึ่งในผู้เล่นที่น่าสนใจที่สุดคนหนึ่งก็คือ GraphQL ด้วยเครื่องมือที่มีให้ครบทั้งฝั่ง client และ server แถมยังมีวิธีการเรียกใช้และจัดการที่น่าสน ผมเลยอดไม่ได้ที่จะขอลอง แต่ถ้าจะไปติดตั้งบน server ก็คงธรรมดาไปใช่ไหมล่ะ บทความนี้ผมจะพาใช้มันบน BaaS อย่าง Firebase Cloud Functions กัน

GraphQL #

GraphQL เป็นตัวกลางที่ช่วยจัดการข้อมูลที่คุณมีอยู่ไม่ว่าจะเป็น database หรือเป็น API อื่นๆ ซึ่งข้อมูลพวกนี้จะถูกเรียกได้ด้วย query language ของ GraphQL เองและถูกกำหนดใน Schema ทุกอย่าง ทำให้คุณไม่ต้องไปเขียน document เพราะ GraphQL จะอ่านทุกอย่างจาก Schema แล้วมาสร้าง document หรือ playground ให้คุณและคนอื่นๆในทีมสามารถสื่อสารกันได้สะดวกมากขึ้น

Firebase Cloud Functions #

Cloud Functions คือบริการหนึ่งใน Firebase ที่จะให้ความช่วยเหลือในด้านการทำ server แต่ไม่ใช่ server ที่ run ตลอดเวลาแบบที่เราใช้กันทั่วไป มันคือ server ที่จะทำงานเฉพาะ function ที่เราเขียนเอาไว้ แล้วก็ทำเฉพาะเวลาที่มี trigger ด้วย เช่น HTTP Request, มีการเขียนหรือแก้ไขใน FireStore Database เป็นต้น​ ซึ่งการทำงานแบบนี้บางคนก็มองว่ามันไม่เปลืองทรัพยากรดี เพราะทำงานเฉพาะเวลาที่มีคนเรียกใช้แล้วก็ปิดตัวไป ไม่ต้องรันเครื่องเอาไว้กินตังค์ทั้งเดือน บริการนี้เลยเหมาะกับงานอะไรที่ทำครั้งเดียวแล้วจบ ไม่มีการรันทิ้งไว้นานๆ

เตรียมพร้อม #

เข้าไปสร้าง Project ใหม่ที่ Firebase เอาไว้ครับผม ใครที่มี Google Account อยู่แล้วก็สามารถเข้าใช้งานได้เลย และไม่ต้องห่วงครับเนื้อหาในบทความนี้ อยู่ใน Free tier ของ Firebase อยู่แล้วคุณไม่จำเป็นต้องผูกบัตรใดๆ

สร้าง Firebase Project

เสร็จแล้วต่อไปนี้เราก็จะเปิด Terminal กันเลยครับ

วิธีการติดตั้ง #

ในบทความนี้ผมจะขอพูดถึงการติดตั้งคร่าวๆเท่านั้นนะครับ จะไม่มีการลงลึกถึงการใช้งานหรือการเรียกใช้ Firestore database อะไรแบบนั้นนะครับ มาดูกันก่อนว่าในการติดตั้งเราจะใช้อะไรกันบ้างครับ

  • Express.js เนื่องจากเราจะใช้งาน Trigger ที่เป็น https.onRequest() สำหรับคนที่ใช้ NodeJS จะมีเครื่องมือไหนคุ้นมือเท่า Express อีกแล้วล่ะครับ
  • apollo-server-express ตัว Apollo Server ก็คือ GraphQL Server เจ้านึงครับ ซึ่งเขาก็มีทั้งขายบริการด้วย แล้วก็ Opensource ตัว server ให้เราไปติดตั้งเองได้ด้วย ซึ่งตัวนี้ Apollo Community เขาก็สร้างตัว Integration ระหว่าง Express กับ GraphQL ให้เราแล้วงานนี้เลยสบาย

อธิบายเครื่องมือคร่าวๆแล้วเดี๋ยวมาเริ่มกันเลยดีกว่า ใครที่ยังไม่มี Node ให้ไปติดตั้งให้เรียบร้อยก่อนนะครับ

  1. เริ่มจากติดตั้ง Firebase CLI ก่อนครับ

npm install -g firebase-tools

  1. แล้วก็ทำการ login ใน terminal เลยนะครับ คำสั่งนี้จะเปิด web browser ขึ้นมาให้เรา login Google Account ที่เราพึ่งสร้าง project ไปเมื่อสักครู่นั่นแหละครับ

firebase login

  1. สร้างโฟลเดอร์ของ project นี้กันครับ

mkdir sample-gql-cf && cd sample-gql-cf

  1. Initialize ตัว project ด้วยคำสั่ง

firebase init

คำถามแรกในคำสั่งนี้คือ เราต้องการให้ตัว Firebase CLI สร้างโฟลเดอร์เตรียมไว้สำหรับ feature ไหนบ้าง บทความนี้เราใช้แค่ Functions ครับ

❯◉ Functions: Configure and deploy Cloud Functions

กด Space เพื่อเลือกแล้วค่อย Enter เพื่อยืนยันนะครับ หลังจากนั้นก็เลือกชื่อ Project ที่เราสร้างไว้ตอนแรกครับ ผมเลือกไว้แบบนี้นะครับ

Initialize firebase project

หลังจากเสร็จจากตรงนี้เราจะได้ไฟล์ชื่อ firebase.json กับโฟลเดอร์ชื่อ functions นะครับ

  1. ติดตั้ง package ที่ต้องใช้

cd functions

npm install express apollo-server-express graphql

  1. เปิด Code Editor ของคุณขึ้นมาได้เลยครับ บทความนี้ผมจะใช้ Visual Studio Code นะครับ

code .

ในโฟลเดอร์ functions จะประกอบไปด้วย

  • node_modules อันนี้เราไม่แตะต้องมันครับ ปล่อยมันหนักอยู่ตรงนั้นแหละ
  • .eslintrc.json ใครที่เลือกใช้ ESLint ไฟล์นี้จะถูกสร้างขึ้นมาครับ สามารถเข้าไปปรับแต่งได้ตามใจชอบซึ่งอันนี้ไม่กล่าวถึงนะ
  • .gitignore เอาไว้บอกให้ git มองข้ามไฟล์หรือโฟลเดอร์ไหนบ้าง โดยเฉพาะ node_modules อย่าได้เผลอเอามันติดไปด้วยนะ
  • package.json และ package-lock.json เอาไว้ config ตัว package ที่เราใช้ครับ แต่จริงๆเรา install มาหมดแล้วก็ไม่ต้องไปแก้ไขอะไรหรอก
  • index.js อันนี้ได้แก้แน่นอนครับ ศูนย์กลางของ project อยู่ที่นี่
  1. สร้างโฟลเดอร์ใหม่แล้วก็ไฟล์ข้างในดังนี้ครับ
graphql
 - schema.js
 - resolver.js
 - server.js
  1. schema.js จะเขียนกำหนด schema ของ api เอาไว้นะครับว่าจะมีอะไรบ้าง ซึ่งตัวอย่างนี้จะมีแค่ Query อย่างเดียว คือ hi ที่จะ return ค่า String กลับไปให้ client ที่เรียกมัน
const { gql } = require('apollo-server-express');

const schema = gql`
  type Query {
    hi: String
  }
`;

module.exports = schema;
  1. resolver.js หลังจากเขียน schema แล้ว resovler ก็คือส่วนที่เป็น function การทำงานจริงๆครับ ไม่ว่าจะเป็นการไป query เอา data จาก database หรือจะคำนวณอะไรก็แล้วแต่ มันจะอยู่ใน Resolver นี่แหละ ตัวอย่างนี้ผมก็ให้ function hi return string โง่ๆกลับไปหนึ่งชุดคือ Hello from GraphQL นะครับ
const resolverFunctions = {
    Query: {
        hi: () => 'Hello from GraphQL'
    }
};

module.exports = resolverFunctions;
  1. server.js ตั้งค่าตัว apollo server กันตรงนี้ครับ ทั้ง schema และ resolver จะถูกเรียกมาไว้ในตัว ApolloServer ด้วย แน่นอนว่าผมจะ enable playground เอาไว้ครับ สำหรับทดสอบการใช้งานกัน และเพื่อให้ playground ทำการ call ไปยัง server ได้ก็ต้อง enable cors ไว้ด้วยเช่นกัน
const express = require('express');
const { ApolloServer } = require('apollo-server-express');

const schema = require('./schema');
const resolvers = require('./resolvers');

const gqlServer = () => {
    const app = express();

    const apolloServer = new ApolloServer({
        typeDefs: schema,
        resolvers,
        introspection: true,
        playground: true
    });

    apolloServer.applyMiddleware({ app, path: '/', cors: true });

    return app;
}

module.exports = gqlServer
  1. กลับมาที่ index.js เราจะเอา gqlServer ซึ่งเป็น apollo-server ที่รวมร่างกับ express แล้วมาใช้ตอนที่ถูก trigger ด้วย https.onRequest() นั่นเอง
const { https } = require('firebase-functions');
const gqlServer = require('./graphql/server');

const server = gqlServer();

const api = https.onRequest(server);

module.exports = {
    api
}
  1. ทดลอง run ในเครื่องของเราดูก่อนครับ โดยกลับไปที่โฟลเดอร์ functions ใน terminal แล้วใช้คำสั่ง

npm run serve

ถ้าไม่มีปัญหาอะไรเราจะได้ url มาครับ อย่างของผมเป็น http://localhost:5000/sample-gql-cf/us-central1/api เมื่อเอาไปเปิดบน browser ก็จะได้เห็น playground ที่สวยงาม ผมลอง query ตามที่เขียนไปดูเราก็จะได้ response กลับมาว่า “Hello from GraphQL” เรียบร้อย

ทดสอบบน local
  1. สุดท้ายทำการ deploy ไปยัง Firebase ด้วยคำสั่ง

npm run deploy

เรียบร้อยแล้วเราก็จะได้ url ของจริงมาครับ ก็ลองเอาไปเปิดบน browser ได้เลยเช่นกันแต่ ท่านอาจจะเจอ error แบบนี้

Error ที่อาจจะพบหลังจาก deploy

ไม่ต้องตกใจครับ path มันผิดแค่พิมพ์คำว่า /api ต่อท้ายเข้าไปก็จะจบครับ

ใช้งานได้สมบูรณ์บน Firebase

ตัวอย่าง code #

https://github.com/clonezer/gql-cf-sample

การใช้ Cloud Functions ถ้าจะเอาไปใช้งานจริงๆ ต้องศึกษาถึงเรื่อง cost ที่อาจจะเกิดอย่างจริงจังด้วยนะครับ เพราะถึงมันจะช่วยเราประหยัดได้แต่ในบางกรณีมันอาจจะแพงกว่าเช่า server เอาก็ได้ สำหรับใครที่เอามาทดลองเล่นๆ หรือเป็น api ที่ใช้กันภายเล็กๆก็น่าเอามาลองใช้ดูครับ